function varargout = ViewNiftiAfni(varargin) %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Visualization HUB for viewing 3D or 4D NIFTI and AFNI files. % % Last modified: Feb. 26, 2014 % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Copyright (C) 2013-2014, Michael J. Cheung % % This file is a part of the MEG & PLS Pipeline (MEGPLS). For more % details, see the documentation included with the software package. % % MEGPLS is free software: you can redistribute it and/or modify it under % the terms of the GNU General Public License version 2 as published by % the Free Software Foundation. This program is distributed in the hope % that it will be useful, but WITHOUT ANY WARRANTY; without even the % implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. % See the GNU General Public License for more details. % % You should have received a copy of the GNU General Public License along % with this program. If not, you can download the license here: % . % Last Modified by GUIDE v2.5 28-Nov-2013 16:27:01 % Begin initialization code - DO NOT EDIT gui_Singleton = 1; gui_State = struct('gui_Name', mfilename, ... 'gui_Singleton', gui_Singleton, ... 'gui_OpeningFcn', @ViewNiftiAfni_OpeningFcn, ... 'gui_OutputFcn', @ViewNiftiAfni_OutputFcn, ... 'gui_LayoutFcn', [] , ... 'gui_Callback', []); if nargin && ischar(varargin{1}) gui_State.gui_Callback = str2func(varargin{1}); end if nargout [varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:}); else gui_mainfcn(gui_State, varargin{:}); end % End initialization code - DO NOT EDIT %--- Executes just before ViewNiftiAfni is made visible. ---% %------------------------------------------------------------% function ViewNiftiAfni_OpeningFcn(hObject, eventdata, handles, varargin) % This function has no output args, see OutputFcn. % hObject handle to figure % eventdata reserved - to be defined in a future version of MATLAB % handles structure with handles and user data (see GUIDATA) % varargin command line arguments to ViewNiftiAfni (see VARARGIN) % Choose default command line output for ViewNiftiAfni handles.output = hObject; % Make sure toolbox paths are added: [PipelineDir, ~, ~] = fileparts(which('ViewNiftiAfni.m')); addpath(genpath(PipelineDir)); rmpath([PipelineDir,'/DEFAULT_SETTINGS']); % Make sure its calling from AnalysisID rmpath([PipelineDir,'/TEMPORARY_FIXES']); % Make sure its calling from FT toolbox CheckToolboxPaths(PipelineDir); % Initialize variables: handles.paths.SelectedAnatFile = ... [PipelineDir,'/MEGPLS_TOOLBOX/Masks_Templates/template_ch2+tlrc.BRIK']; set(handles.TextboxAnatFile, 'String', handles.paths.SelectedAnatFile); handles.gui.NiftiAfniList = []; handles.paths.NiftiAfniDir = []; handles.paths.SelectedFuncFile = []; % Update handles structure guidata(hObject, handles); % UIWAIT makes ViewNiftiAfni wait for user response (see UIRESUME) % uiwait(handles.figure1); %--- Outputs from this function are returned to the command line. ---% %--------------------------------------------------------------------% function varargout = ViewNiftiAfni_OutputFcn(hObject, eventdata, handles) % varargout cell array for returning output args (see VARARGOUT); % hObject handle to figure % eventdata reserved - to be defined in a future version of MATLAB % handles structure with handles and user data (see GUIDATA) % Get default command line output from handles structure varargout{1} = handles.output; %====================================% % FUNCTIONS FOR ANATOMICAL UNDERLAY: % %====================================% %--- Textbox to display selected anatomical .BRIK file: ---% %----------------------------------------------------------% function TextboxAnatFile_Callback(hObject, eventdata, handles) EnteredText = get(handles.TextboxAnatFile, 'String'); if ~isequal(EnteredText, handles.paths.SelectedAnatFile) set(handles.TextboxAnatFile, 'String', handles.paths.SelectedAnatFile); msgbox('Note: Use button to change anatomy file.'); end %--- Executes on button press in ButtonAnatFile. ---% %---------------------------------------------------% function ButtonAnatFile_Callback(hObject, eventdata, handles) [AnatPath, ~, ~] = fileparts(handles.paths.SelectedAnatFile); [BrikFile, BrikPath] = uigetfile([AnatPath,'/*+tlrc.BRIK'], ... 'Select anatomical underlay .BRIK file.', 'MultiSelect', 'off'); if BrikFile == 0 return; % If user cancels end % Set anatomy file: handles.paths.SelectedAnatFile = [BrikPath,BrikFile]; set(handles.TextboxAnatFile, 'String', handles.paths.SelectedAnatFile) % Save handles: guidata(hObject, handles); %=============================================% % FUNCTIONS FOR AFNI OR NIFTI FILE SELECTION: % %=============================================% %--- Textbox to display selected target directory: ---% %-----------------------------------------------------% function TextboxNiftiAfniDir_Callback(hObject, eventdata, handles) EnteredText = get(handles.TextboxNiftiAfniDir, 'String'); if ~isequal(EnteredText, handles.paths.NiftiAfniDir) set(handles.TextboxNiftiAfniDir, 'String', handles.paths.NiftiAfniDir); msgbox('Note: Use button to change search directory.'); end %--- Executes on selection change in ListboxNiftiAfniFiles. ---% %---------------------------------------------------------------% function ListboxNiftiAfniFiles_Callback(hObject, eventdata, handles) if isempty(handles.paths.NiftiAfniDir) || isempty(handles.gui.NiftiAfniList) return; end handles = DetectSelectedFiles(handles); guidata(hObject, handles); %--- Executes on button press in ButtonNiftiAfniDir. ---% %--------------------------------------------------------% function ButtonNiftiAfniDir_Callback(hObject, eventdata, handles) if ~isempty(handles.paths.NiftiAfniDir) [OneUpDir, ~, ~] = fileparts(handles.paths.NiftiAfniDir); else OneUpDir = []; end SelectedPath = uigetdir(OneUpDir, 'Select directory for AFNI or NIFTI files:'); if SelectedPath == 0 return; % If user cancels end % Get list of AFNI & NIFTI files: AfniFiles = dir([SelectedPath,'/*+tlrc.BRIK']); NiftiFiles = dir([SelectedPath,'/*.nii']); if isempty(AfniFiles) && isempty(NiftiFiles) msgbox('Error: No AFNI or NIFTI files found inside directory.', 'Error:') return; end % Set current path and available files: handles.paths.NiftiAfniDir = SelectedPath; set(handles.TextboxNiftiAfniDir, 'String', handles.paths.NiftiAfniDir); AfniFiles = {AfniFiles.name}'; NiftiFiles = {NiftiFiles.name}'; handles.gui.NiftiAfniList = [AfniFiles; NiftiFiles]; handles = UpdateNiftiAfniListbox (handles); handles = DetectSelectedFiles (handles); % Save handles: guidata(hObject, handles); %--- Acquire currently selected NIFTI / AFNI file: ---% %-----------------------------------------------------% function OutputHandles = DetectSelectedFiles(InputHandles) handles = InputHandles; % Get selected file: SelectedIndex = get(handles.ListboxNiftiAfniFiles, 'Value'); SelectedFile = handles.gui.NiftiAfniList{SelectedIndex}; handles.paths.SelectedFuncFile = []; handles.paths.SelectedFuncFile = strcat([handles.paths.NiftiAfniDir,'/'], SelectedFile); % Set output handles: OutputHandles = handles; %--- Update NIFTI / AFNI settings: ---% %-------------------------------------% function OutputHandles = UpdateNiftiAfniListbox(InputHandles) handles = InputHandles; % Update AFNI / NIFTI listbox: set(handles.ListboxNiftiAfniFiles, 'String', handles.gui.NiftiAfniList); CurrentIndex = get(handles.ListboxNiftiAfniFiles, 'Value'); MaxIndex = length(handles.gui.NiftiAfniList); if isempty(CurrentIndex) || CurrentIndex == 0 || CurrentIndex > MaxIndex set(handles.ListboxNiftiAfniFiles, 'Value', MaxIndex); end % Set output handles: OutputHandles = handles; %=========================% % FUNCTIONS FOR PLOTTING: % %=========================% %--- Executes on button press in ButtonTimeLegend. ---% %-----------------------------------------------------% function ButtonTimeLegend_Callback(hObject, eventdata, handles) if isempty(handles.paths.NiftiAfniDir) msgbox('Error: Directory for AFNI / NIFTI files not selected.', 'Error:') return; end [LegendFile, LegendPath] = uigetfile([handles.paths.NiftiAfniDir,'/*_TimeLegend.txt'], ... 'Select TimeLegend file to load:', 'MultiSelect', 'off'); if LegendFile == 0 return; % If user cancels else open([LegendPath,LegendFile]); end %--- Converts NIFTI file to temporary AFNI for viewing: ---% %----------------------------------------------------------% function OutputAfni = ConvertNifti2Afni(InputNifti) % Get parameters for conversion to AFNI: [NiiFolder, NiiName, ~] = fileparts(InputNifti); TempAfniFile = [NiiFolder,'/',NiiName,'+tlrc.BRIK']; prompt = {'Associate NIFTI file with what template for AFNI conversion?'; 'Note: If file was generated by MEGPLS pipeline, choose MNI.'} AfniSpace = questdlg(prompt, 'Template?', 'mni', 'tlrc', 'orig', 'mni'); PipeSettings.Afni4D.NaNFix = 'yes'; PipeSettings.Afni4D.Template = AfniSpace; % Convert selected NIFTI file to AFNI: if exist(TempAfniFile, 'file') delete(TempAfniFile); delete([NiiFolder,'/',NiiName,'+tlrc.HEAD']); end CheckSavePath(TempAfniFile, 'ViewNiftiAfni'); MEGpipeline_Nifti2Afni_Guts(PipeSettings, InputNifti, TempAfniFile); % Set output AFNI file: OutputAfni = TempAfniFile; %--- Executes on button press in ButtonView4DBRIK. ---% %-----------------------------------------------------% function ButtonView4DBRIK_Callback(hObject, eventdata, handles) if isempty(handles.paths.SelectedAnatFile) msgbox('Error: Anatomical underlay not selected.', 'Error:'); return; end if isempty(handles.paths.NiftiAfniDir) msgbox('Error: AFNI / NIFTI directory not selected.', 'Error:'); return; end if isempty(handles.paths.SelectedFuncFile) msgbox('Error: AFNI / NIFTI file not selected.', 'Error:'); return; end % Check if paths have spaces in them (AFNI paths cannot support spaces): CheckSpaces1 = strfind(handles.paths.NiftiAfniDir, ' '); CheckSpaces2 = strfind(handles.paths.SelectedAnatFile, ' '); CheckSpaces3 = strfind(handles.paths.SelectedFuncFile, ' '); if ~isempty(CheckSpaces1) || ~isempty(CheckSpaces2) || ~isempty(CheckSpaces3) msgbox('Error: AFNI fcns cannot read folder & file paths containing spaces.', 'Error:') return; end % Update selected files: handles = UpdateNiftiAfniListbox (handles); handles = DetectSelectedFiles (handles); % Create temp viewing directory: TempViewFolder = [handles.paths.NiftiAfniDir,'/TEMP_VIEWER_FILES']; if ~exist(TempViewFolder, 'dir') status = mkdir(TempViewFolder); if status == 0 msgbox('Error: Failed to create viewing folder in selected directory.'); return; end end % Get temp file paths: [~, AnatFile, AnatExt] = fileparts(handles.paths.SelectedAnatFile); [~, FuncFile, FuncExt] = fileparts(handles.paths.SelectedFuncFile); TempAnatFile = [TempViewFolder,'/',AnatFile,AnatExt]; TempFuncFile = [TempViewFolder,'/',FuncFile,FuncExt]; if exist(TempAnatFile, 'file') delete(TempAnatFile); delete([TempViewFolder,'/',AnatFile,'.HEAD']); end if exist(TempFuncFile, 'file') delete(TempFuncFile); if strcmp(FuncExt, '.BRIK') delete([TempViewFolder,'/',FuncFile,'.HEAD']); end end % Copy func file to temp view folder & convert to AFNI if needed: if strcmp(FuncExt, '.nii') copyfile(handles.paths.SelectedFuncFile, TempFuncFile, 'f'); TempFuncFile = ConvertNifti2Afni(TempFuncFile); elseif strcmp(FuncExt, '.BRIK') system(['3dcopy ',handles.paths.SelectedFuncFile,' ',TempFuncFile]); end % Copy anatomy file to temp view folder & resample if needed: system(['3dcopy ',handles.paths.SelectedAnatFile,' ',TempAnatFile]); TempAnatFile = MEGpipeline_AfniResampleAnat(TempAnatFile, TempFuncFile); if isempty(TempAnatFile) msgbox('Error: Failed to resample anatomy file.', 'Error:'); return; end % Check if file is 4D: CurrentDir = pwd; Opt.format = 'vector'; cd(TempViewFolder); [~, CheckFunc, ~, ~] = BrikLoad(TempFuncFile, Opt); cd(CurrentDir); if numel(size(CheckFunc)) ~= 4 msgbox('Error: Selected file is not 4D file. Use "View in AFNI" instead.'); return; end % Run View4D_BRIK: View4D_BRIK(TempAnatFile, TempFuncFile, [], []); %--- Executes on button press in ButtonViewAFNI. ---% %---------------------------------------------------% function ButtonViewAFNI_Callback(hObject, eventdata, handles) if isempty(handles.paths.SelectedAnatFile) msgbox('Error: Anatomical underlay not selected.', 'Error:'); return; end if isempty(handles.paths.NiftiAfniDir) msgbox('Error: AFNI /NIFTI directory not selected.', 'Error:'); return; end if isempty(handles.paths.SelectedFuncFile) msgbox('Error: AFNI / NIFTI file not selected.', 'Error:'); return; end % Check if paths have spaces in them (AFNI paths cannot support spaces): CheckSpaces1 = strfind(handles.paths.NiftiAfniDir, ' '); CheckSpaces2 = strfind(handles.paths.SelectedAnatFile, ' '); CheckSpaces3 = strfind(handles.paths.SelectedFuncFile, ' '); if ~isempty(CheckSpaces1) || ~isempty(CheckSpaces2) || ~isempty(CheckSpaces3) msgbox('Error: AFNI fcns cannot read folder & file paths containing spaces.', 'Error:') return; end % Update selected files: handles = UpdateNiftiAfniListbox (handles); handles = DetectSelectedFiles (handles); % Create temp viewing directory: TempViewFolder = [handles.paths.NiftiAfniDir,'/TEMP_VIEWER_FILES']; if ~exist(TempViewFolder, 'dir') status = mkdir(TempViewFolder); if status == 0 msgbox('Error: Failed to create viewing folder in selected directory.'); return; end end % Get temp file paths: [~, AnatFile, AnatExt] = fileparts(handles.paths.SelectedAnatFile); [~, FuncFile, FuncExt] = fileparts(handles.paths.SelectedFuncFile); TempAnatFile = [TempViewFolder,'/',AnatFile,AnatExt]; TempFuncFile = [TempViewFolder,'/',FuncFile,FuncExt]; if exist(TempAnatFile, 'file') delete(TempAnatFile); delete([TempViewFolder,'/',AnatFile,'.HEAD']); end if exist(TempFuncFile, 'file') delete(TempFuncFile); if strcmp(FuncExt, '.BRIK') delete([TempViewFolder,'/',FuncFile,'.HEAD']); end end % Copy func file to temp view folder & convert to AFNI if needed: if strcmp(FuncExt, '.nii') copyfile(handles.paths.SelectedFuncFile, TempFuncFile, 'f'); TempFuncFile = ConvertNifti2Afni(TempFuncFile); elseif strcmp(FuncExt, '.BRIK') system(['3dcopy ',handles.paths.SelectedFuncFile,' ',TempFuncFile]); end % Copy anatomy file to temp view folder & create resample if needed: % Note: Do not change TempAnatFile to resampled version (want high-res as default input). system(['3dcopy ',handles.paths.SelectedAnatFile,' ',TempAnatFile]); ResampledAnat = MEGpipeline_AfniResampleAnat(TempAnatFile, TempFuncFile); if isempty(ResampledAnat) msgbox('Warning: Failed to resample anatomy file.', 'Error:'); end % Prepare file calls to AFNI: [~, AnatName, ~] = fileparts(TempAnatFile); AnatName(end-4:end) = []; % Remove +view label [~, FuncName, ~] = fileparts(TempFuncFile); FuncName(end-4:end) = []; % Set environmental variables: setenv('AFNI_SLAVE_FUNCTIME', 'YES'); % Locks overlay with time-index (Newer versions). setenv('AFNI_SLAVE_BUCKETS_TOO', 'YES'); % Locks overlay with time-index (Older versions). setenv('AFNI_SLAVE_THRTIME', 'YES'); % Locks threshold with time-index (Older versions). setenv('AFNI_SLAVE_THROLAY', 'OLay'); % Locks threshold with time-index (Newer versions). setenv('AFNI_LEFT_IS_LEFT', 'YES'); % Sets images to neurological view. setenv('AFNI_THRESH_AUTO', 'NO'); % Threshold slider does not change automatically. setenv('AFNI_THRESH_LOCK', 'VALUE'); setenv('AFNI_FLOATSCAN', 'YES'); if strcmp(getenv('AFNI_LEFT_IS_LEFT'), 'NO') msgbox('NOTE: "AFNI_LEFT_IS_LEFT" env. variable is now set to ''YES''.') end % Open AFNI command: CmdLine = ['afni -com ''' ... 'OPEN_WINDOW A.axialimage;' ... ' OPEN_WINDOW A.sagittalimage;' ... ' OPEN_WINDOW A.coronalimage;' ... ' SWITCH_UNDERLAY A.',AnatName,';' ... % Underlay .BRIK ' SWITCH_OVERLAY A.',FuncName,';' ... % Overlay .BRIK ' SET_SUBBRICKS A 1 1 1;' ... % Sets .BRIK index to 1 ' SET_FUNC_AUTORANGE A.+;' ... % Turns ON autorange ' REDISPLAY;'' &']; CurrentDir = pwd; cd(TempViewFolder); system(CmdLine); cd(CurrentDir); %============================% % GUIDE CREATEFCN FUNCTIONS: % %============================% % --- Executes during object creation, after setting all properties. function TextboxAnatFile_CreateFcn(hObject, eventdata, handles) if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) set(hObject,'BackgroundColor','white'); end % --- Executes during object creation, after setting all properties. function TextboxNiftiAfniDir_CreateFcn(hObject, eventdata, handles) if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) set(hObject,'BackgroundColor','white'); end % --- Executes during object creation, after setting all properties. function ListboxNiftiAfniFiles_CreateFcn(hObject, eventdata, handles) if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) set(hObject,'BackgroundColor','white'); end